package cn.edu.stu.syllabus.oa.star;

import com.orhanobut.logger.Logger;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.inject.Inject;

import cn.edu.stu.syllabus.datas.RequestState;
import cn.edu.stu.syllabus.di.scope.FragmentScoped;
import cn.edu.stu.syllabus.repository.oa.OaStarDataRepository;
import cn.edu.stu.syllabus.repository.oa.local.OaInfoEntry;
import cn.edu.stu.syllabus.utils.ExtraNameJoiner;
import cn.edu.stu.syllabus.utils.ListUtils;
import cn.edu.stu.syllabus.utils.RxSchedulerUtils;
import rx.Subscriber;
import rx.Subscription;
import rx.subscriptions.CompositeSubscription;

import static cn.edu.stu.syllabus.utils.NullPointerUtils.checkNotNull;

/**
 * Created by daidaijie on 2017/3/21.
 */

@FragmentScoped
public class OaStarPresenter implements OaStarContract.Presenter {


    private final OaStarContract.View mView;

    private final OaStarDataRepository mOaStarDataRepository;

    private CompositeSubscription mCompositeSubscription;

    private long mLastEndPositionId;

    private static final int OA_PAGE_NUM = 10;

    private List<OaInfoEntry> mOaInfoEntries;

    private int mRequestState;

    private static final String EXTRA_OA_INFO_ENTRY = ExtraNameJoiner.join(
            OaStarPresenter.class, "mOaInfoEntries"
    );

    private static final String EXTRA_LAST_END_POSITION_ID = ExtraNameJoiner.join(
            OaStarPresenter.class, "mLastEndPositionId"
    );

    private static final String EXTRA_REQUEST_STATE = ExtraNameJoiner.join(
            OaStarPresenter.class, "mRequestState"
    );

    @Inject
    public OaStarPresenter(OaStarContract.View view, OaStarDataRepository oaStarDataRepository) {
        mView = checkNotNull(view);
        mOaStarDataRepository = checkNotNull(oaStarDataRepository);
        mCompositeSubscription = new CompositeSubscription();
    }

    @Inject
    public void setupListeners() {
        mView.setPresenter(this);
    }

    @Override
    public void subscribe() {
        if (mOaInfoEntries == null) {
            if (RequestState.isEmpty(mRequestState)) {
                mView.showDataEmpty();
            } else if (RequestState.isError(mRequestState)) {
                mView.showDataError();
            } else {
                mRequestState = RequestState.REQUEST_FIRST;
                loadStarOaEntries();
            }
        } else {
            mView.setOaInfoList(mOaInfoEntries);
            if (RequestState.isEmpty(mRequestState)) {
                mView.showLoadingEnd();
            } else if (RequestState.isError(mRequestState)) {
                mView.showLoadingFail();
            }
        }
    }

    @Override
    public void unsubscribe() {
        mCompositeSubscription.unsubscribe();
    }

    @Override
    public void loadStarOaEntries() {
        if (RequestState.isFirst(mRequestState)) {
            mLastEndPositionId = Long.MAX_VALUE;
        }

        Subscription subscription = mOaStarDataRepository
                .getStarOaInfoEntries(mLastEndPositionId, OA_PAGE_NUM)
                .compose(RxSchedulerUtils.<List<OaInfoEntry>>io2mainSchedulersTransformer())
                .subscribe(new Subscriber<List<OaInfoEntry>>() {
                    @Override
                    public void onCompleted() {
                    }

                    @Override
                    public void onError(Throwable e) {
                        if (RequestState.isFirst(mRequestState)) {
                            mView.showDataError();
                        } else {
                            mView.showLoadingFail();
                        }
                        mRequestState = RequestState.REQUEST_ERROR;
                    }

                    @Override
                    public void onNext(List<OaInfoEntry> oaInfoEntries) {
                        if (ListUtils.getListSizeSafety(oaInfoEntries) > 0) {
                            if (RequestState.isFirst(mRequestState)) {
                                mOaInfoEntries = oaInfoEntries;
                                mView.setOaInfoList(oaInfoEntries);
                            } else {
                                mView.appendOaInfoList(oaInfoEntries);
                            }
                            mLastEndPositionId = oaInfoEntries.get(oaInfoEntries.size() - 1).getMLocalId();
                            mRequestState = RequestState.REQUEST_SUCCESS;
                        } else {
                            if (RequestState.isFirst(mRequestState)) {
                                mView.showDataEmpty();
                            } else {
                                mView.showLoadingEnd();
                            }
                            mRequestState = RequestState.REQUEST_EMPTY;
                        }
                    }
                });

        mCompositeSubscription.add(subscription);
    }

    @Override
    public void unstarOaInfo(OaInfoEntry oaInfoEntry, int position) {
        mOaStarDataRepository.unstarOaInfoEntry(oaInfoEntry);
        mView.removeUnstarOaInfo(position);
    }


    @Override
    public Map<String, Object> getStoreData() {
        Map<String, Object> storeData = new HashMap<>();
        storeData.put(EXTRA_OA_INFO_ENTRY, mOaInfoEntries);
        storeData.put(EXTRA_LAST_END_POSITION_ID, mLastEndPositionId);
        storeData.put(EXTRA_REQUEST_STATE, mRequestState);
        return storeData;
    }

    @Override
    public void restoreData(Map<String, Object> storeData) {
        mOaInfoEntries = (List<OaInfoEntry>) storeData.get(EXTRA_OA_INFO_ENTRY);
        mLastEndPositionId = (long) storeData.get(EXTRA_LAST_END_POSITION_ID);
        mRequestState = (int) storeData.get(EXTRA_REQUEST_STATE);
    }
}
